package controllers

import (
	"baokaobang/conf"
	"baokaobang/utils"
	"fmt"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"
	"github.com/nfnt/resize"
	imgtype "github.com/shamsher31/goimgtype"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"os"
	"path"
	"time"
)

type UploadController struct {
	Ctx iris.Context
}

func (c *UploadController) Options() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *UploadController) Post() interface{} {
	fileType := c.Ctx.PostValueDefault("fileType", "")	
	if len(fileType) <= 0 {
		return utils.CommonRes(1000, "请指定文件类型", "")
	}
	maxSize := int64(10 << 20) // 10MB
	file, info, err := c.Ctx.FormFile("file")
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("文件上传失败：%s", err.Error()), "")
	}
	if info.Size > maxSize {
		return utils.CommonRes(1000, "文件大小超过10M", "")
	}
	defer file.Close()

	prefix := conf.UploadPrefix.Front
	ext := path.Ext(info.Filename)
	t := time.Now().Format("20060102")
	d := fmt.Sprintf("/uploadfiles/%s/%s", fileType, t)
	_, err = os.Stat(d)
	if err != nil {
		err := os.MkdirAll(fmt.Sprintf("%s%s", prefix, d), os.ModePerm)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("文件上传目录创建失败：%s", err.Error()), "")
		}
	}

	n := utils.Md5Encode(fmt.Sprintf("%d", time.Now().UnixNano()))
	toFile := fmt.Sprintf("%s%s/%s%s", prefix, d, n, ext)
	out, err := os.Create(toFile)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("文件创建失败：%s", err.Error()), "")
	}
	defer out.Close()
	_, err = io.Copy(out, file)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("文件上传失败：%s", err.Error()), "")
	}

	if fileType == "images" { // 如果上传的是图片，则进行压缩

		var imgFile *os.File

		imgFile, err = os.Open(toFile)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("上传的图片无法打开：%s", err.Error()), "")
		}
		defer imgFile.Close()

		var img image.Image
		var imageType string
		var w int

		imageType, err = imgtype.Get(toFile)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("无法获取图片类型：%s", err.Error()), "")
		}

		switch imageType {
		case `image/jpeg`:
			img, err = jpeg.Decode(imgFile)
		case `image/png`:
			img, err = png.Decode(imgFile)
		default:
			return utils.CommonRes(1000, "未知图片类型", "")
		}
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析图片出错：%s", err.Error()), "")
		}

		w = img.Bounds().Dx()
		if w > 800 { // 对宽度大于800像素的图片进行压缩
			m := resize.Resize(800, 0, img, resize.NearestNeighbor)
			compressName := fmt.Sprintf("%s%s", utils.Md5Encode(fmt.Sprintf("%d", time.Now().UnixNano() + 1)), ext)
			imgOut, err := os.Create(fmt.Sprintf("%s%s/%s", prefix, d, compressName))
			if err != nil {
				return utils.CommonRes(1000, fmt.Sprintf("压缩图片出错：%s", err.Error()), "")
			}
			defer imgOut.Close()

			o := &jpeg.Options{
				Quality: 80,
			}
			err = jpeg.Encode(imgOut, m, o)
			if err != nil {
				return utils.CommonRes(1000, fmt.Sprintf("压缩后的图片保存出错：%s", err.Error()), "")
			}

			os.Remove(toFile)
			return utils.CommonRes(20000, "成功上传", map[string]string{"url": fmt.Sprintf("%s/%s", d, compressName)})
		}

	}

	return utils.CommonRes(20000, "成功上传", map[string]string{"url": fmt.Sprintf("%s/%s%s", d, n, ext)})
}

func (c *UploadController) OptionsBackend() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *UploadController) PostBackend() interface{} {
	fileType := c.Ctx.PostValue("fileType")
	maxSize := int64(5 << 20) // 5MB
	file, info, err := c.Ctx.FormFile("file")
	if info.Size > maxSize {
		return utils.CommonRes(1000, fmt.Sprintf("文件大小超过%dM", maxSize), "")
	}
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("文件上传失败:%s", err.Error()), "")
	}

	//syscall.Umask(0)
	defer file.Close()

	prefix := conf.UploadPrefix.Backend
	ext := path.Ext(info.Filename)
	t := time.Now().Format("20060102")
	d := fmt.Sprintf("/static/upload/%s/%s", fileType, t)
	_, err = os.Stat(d)
	if err != nil {
		//mask := syscall.Umask(0)
		//defer syscall.Umask(mask)
		err := os.MkdirAll(fmt.Sprintf("%s%s", prefix, d), os.ModePerm)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("文件上传目录创建失败:%s", err.Error()), "")
		}
	}
	n := utils.Md5Encode(fmt.Sprintf("%d", time.Now().UnixNano()))
	toFile := fmt.Sprintf("%s%s/%s%s", prefix, d, n, ext)
	out, err := os.OpenFile(toFile, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("文件创建失败:%s", err.Error()), "")
	}

	defer out.Close()
	io.Copy(out, file)
	//os.Chmod(toFile, 0666)

	return utils.CommonRes(20000, "成功上传", map[string]string{"url": fmt.Sprintf("%s/%s%s", d, n, ext)})
}
